;___Rom_Monitor_Program_____________________________________________________________________________________________________________
;
;  Original Code by:	Andrew Lynch (lynchaj@yahoo.com)	13 Feb 2007
;
;  Modified by : 	Dan Werner 03.09.2009
;
;__References________________________________________________________________________________________________________________________ 
; Thomas Scherrer basic hardware test assembler sources from the Z80 info page
; including original schematic concept
; http://z80.info/z80sourc.txt
; Code samples from Bruce Jones public domain ROM monitor for the SBC-200C 
; http://www.retrotechnology.com/herbs_stuff/sd_bruce_code.zip
; Inspiration from Joel Owens "Z-80 Space-Time Productions Single Board Computer"
; http://www.joelowens.org/z80/z80index.html
; Great help and technical advice from Allison at ALPACA_DESIGNERS
; http://groups.yahoo.com/group/alpaca_designers
; INTEL SDK-85 ROM Debug Monitor
;
;__Hardware_Interfaces________________________________________________________________________________________________________________ 
;
; PIO 82C55 I/O IS DECODED TO PORT 60-67
;
PORTA		.EQU 	60H
PORTB		.EQU 	61H
PORTC		.EQU 	62H
PIOCONT 	.EQU 	63H
;
; UART 16C450 SERIAL IS DECODED TO 68-6F
;
UART0:		.EQU	68H		;   DATA IN/OUT
UART1:		.EQU	69H		;   CHECK RX
UART2:		.EQU	6AH		;   INTERRUPTS
UART3:		.EQU	6BH		;   LINE CONTROL
UART4:		.EQU	6CH		;   MODEM CONTROL
UART5:		.EQU	6DH		;   LINE STATUS
UART6:		.EQU	6EH		;   MODEM STATUS
UART7:		.EQU	6FH		;   SCRATCH REG.
;
; MEMORY PAGE CONFIGURATION LATCH IS DECODED TO 78
;
MPCL:		.EQU	78H		; CONTROL PORT, SHOULD ONLY BE CHANGED WHILE
;					  IN UPPER MEMORY PAGE $8000-$FFFF OR LIKELY
;					  LOSS OF CPU MEMORY CONTEXT.
;
; MEMORY PAGE CONFIGURATION LATCH CONTROL PORT ( IO_Y3 ) INFORMATION
;
;	7 6 5 4  3 2 1 0      ONLY APPLICABLE TO THE LOWER MEMORY PAGE $0000-$7FFF
;	^ ^ ^ ^  ^ ^ ^ ^
;	: : : :  : : : :--0 = A15 RAM/ROM ADDRESS LINE DEFAULT IS 0
;	: : : :  : : :----0 = A16 RAM/ROM ADDRESS LINE DEFAULT IS 0
;	: : : :  : :------0 = A17 RAM/ROM ADDRESS LINE DEFAULT IS 0
;	: : : :  :--------0 = A18 RAM/ROM ADDRESS LINE DEFAULT IS 0
;	: : : :-----------0 = A19 ROM ONLY ADDRESS LINE DEFAULT IS 0
;	: : :-------------0 = 
;	: :---------------0 = 
;	:-----------------0 = ROM SELECT (0=ROM, 1=RAM) DEFAULT IS 0
;
;
;IDE REGISTER		IO PORT		; FUNCTION
IDELO		.EQU	$20		; DATA PORT (LOW BYTE)
IDEERR		.EQU	$21		; READ: ERROR REGISTER; WRITE: PRECOMP
IDESECTC	.EQU	$22		; SECTOR COUNT
IDESECTN	.EQU	$23		; SECTOR NUMBER
IDECYLLO	.EQU	$24		; CYLINDER LOW
IDECYLHI	.EQU	$25		; CYLINDER HIGH
IDEHEAD		.EQU	$26		; DRIVE/HEAD
IDESTTS		.EQU	$27		; READ: STATUS; WRITE: COMMAND
IDEHI		.EQU	$28		; DATA PORT (HIGH BYTE)
IDECTRL		.EQU	$2E		; READ: ALTERNATIVE STATUS; WRITE; DEVICE CONTROL
IDEADDR		.EQU	$2F		; DRIVE ADDRESS (READ ONLY)

;
;
;__Constants_________________________________________________________________________________________________________________________ 
;	
RAMTOP:		.EQU	$FFFF		; HIGHEST ADDRESSABLE MEMORY LOCATION
STACKSTART:	.EQU	$D3FF		; sTART OF STACK
RAMBOTTOM:	.EQU	$8000		; START OF FIXED UPPER 32K PAGE OF 512KB x 8 RAM 8000H-FFFFH
MONSTARTCOLD:	.EQU	$8000		; COLD START MONITOR IN HIGH RAM
END:		.EQU	$FF		; Mark END OF TEXT
CR:		.EQU	0DH		; ASCII carriage return character
LF:		.EQU	0AH		; ASCII line feed character
ESC:		.EQU	1BH		; ASCII escape character
BS:		.EQU	08H		; ASCII backspace character
;
;
;
;__Main_Program_____________________________________________________________________________________________________________________ 
;
;	.ORG	$0100			; For Debug in CP/M (AS .COM)
	.ORG	8000H			; Normal Op

	LD	SP,STACKSTART		; Set the Stack Pointer to STACKSTART
	CALL	INITIALIZE		; Initialize System

;  REMOVE THIS TO USE THE DSKY BOARD
;	JP	MONSTARTWARM		; 
;

;__FRONT_PANEL_STARTUP___________________________________________________________________________________________________________ 
;
;	Start up the system with the Front Panel Interface
;	
;________________________________________________________________________________________________________________________________
;
	CALL    mTerm_Init		; Init 8255 for mTerm
	LD	HL,CPUUP		; SET POINTER TO DATA BUFFER
	CALL	SEGDISPLAY		; DISPLAY 



FRONTPANELLoop:
	CALL	KB_GET			; Get Key from KB

	CP	10H			; IS Port Read?
	JP	Z,DoPortRead		; YES, JUMP
	CP	11H			; IS Port Write?
	JP	Z,DoPortWrite		; YES, JUMP
	CP	14H			; IS DEPOSIT?
	JP	Z,DoDeposit		; YES, JUMP
	CP	15H			; IS EXAMINE?
	JP	Z,DoExamine		; YES, JUMP
	CP	16H			; IS GO?
	JP	Z,DoGo			; YES, JUMP
	CP	17H			; IS BOOT?
	JP	Z,DoBoot		; YES, JUMP

	JR	FRONTPANELLoop		; LOOP
Exit:
	RET	


;__DoBoot________________________________________________________________________________________________________________________ 
;
;	PERFORM BOOT FRONT PANEL ACTION
;________________________________________________________________________________________________________________________________
;
DoBoot:
	LD	HL,BOOT			; POINT TO BOOT MESSAGE
	CALL 	SEGDISPLAY		; DISPLAY MESSAGE
BOOTGETKEY:
	CALL	KB_GET			; Get Key from KB INTO A
	LD	HL,BOOT			; POINT TO BOOT MESSAGE
	PUSH	AF			; STORE AF
	CALL	DECODEDISPLAY		; DECODE "A" TO 7 SEG
	LD	(HL),A			; STORE VALUE IN A TO DISPLAY BUF
	CALL	SEGDISPLAY		; DISPLAY BUFFER ON 7 SEG
	POP	AF			; RESTORE AF
	CP	12H			; [CL] PRESSED, EXIT
	JP	Z,BootExit		;
	CP	00H			; [0] PRESSED, BOOT SERIAL MONITOR
	JP	Z,MONSTARTWARM		; 
	CP	01H			; [1] PRESSED, BOOT ROM CP/M
	JP	Z,GOCPM			;
	CP	02H			; [2] PRESSED, BOOT ATAPI PRIMARY
	JP	Z,BOOTATAPIPRI		; 
	CP	03H			; [3] PRESSED, BOOT ATAPI SECONDARY
	JP	Z,BOOTATAPISEC		;
	LD	HL,BOOT			; POINT TO BOOT MESSAGE
	LD	A,00H			; BLANK OUT SELECTION,IT WAS INVALID
	LD	(HL),A			; STORE IT IN DISPLAY BUFFER
	CALL	SEGDISPLAY		; DISPLAY THE BUFFER
	JR	BOOTGETKEY		; NO VALID KEY, LOOP
	
BootExit:
	LD	HL,CPUUP		; SET POINTER TO DATA BUFFER
	CALL	SEGDISPLAY		; DISPLAY 
	JP	FRONTPANELLoop		;

BOOTATAPIPRI:
	LD	A,00H
	LD	(IDEDEVICE),A		; SET PRIMARY DEVICE
	JR	BOOTATAPI		;
BOOTATAPISEC:
	LD	A,10H			;
	LD	(IDEDEVICE),A		; SET SECONDARY DEVICE
BOOTATAPI:
	CALL	IDE_SOFT_RESET		;
	LD	HL,SEC			; DISPLAY PROMPT
	CALL	SEGDISPLAY		; 
	LD	DE,0000H		; SET SECTOR HIGH WORD TO 00H
	LD	HL,0000H		; SET SECTOR LOW WORD TO 00H
	LD	IX,0D400H		; SET TOP OF CP/M
	LD	B,19			; SET NUMBER OF SECTORS TO LOAD
BOOTATAPILOOP:
	CALL	DSPSECTOR		;
	CALL	ATAPI_READ_SECTOR	; READ A SECTOR
	INC	HL			; POINT TO NEXT SECTOR
	DJNZ	BOOTATAPILOOP		; LOOP
	JP	0EA00H			; GO TO CP/M


;__DoPortRead____________________________________________________________________________________________________________________ 
;
;	PERFORM PORT READ FRONT PANEL ACTION
;________________________________________________________________________________________________________________________________
;
DoPortRead:	
	CALL 	GETPORT			; GET PORT INTO A
PORTREADLOOP:
	LD	C,A			; STORE PORT IN "C"
	SRL	A			; ROTATE HIGH NIB TO LOW
	SRL	A			;
	SRL	A			;
	SRL	A			;
	LD	(DISPLAYBUF+5),A	; SHOW HIGH NIB IN DISP 5
	LD	A,C			; RESTORE PORT VALUE INTO "A"
	AND	0FH			; CLEAR HIGH NIB, LEAVING LOW
	LD	(DISPLAYBUF+4),A	; SHOW LOW NIB IN DISP 4
	IN 	A,(C)			; GET PORT VALUE FROM PORT IN "C"
	LD	C,A			; STORE VALUE IN "C"
	SRL	A			; ROTATE HIGH NIB TO LOW
	SRL	A			;
	SRL	A			;
	SRL	A			;
	LD	(DISPLAYBUF+1),A	; SHOW HIGH NIB IN DISP 1
	LD	A,C			; RESTORE VALUE TO "A"
	AND	0FH			; CLEAR HIGH NIB, LEAVING LOW
	LD	(DISPLAYBUF),A		; DISPLAY LOW NIB IN DISP 0
	LD	A,10H			; CLEAR OTHER DISPLAYS
	LD	(DISPLAYBUF+2),A	;
	LD	(DISPLAYBUF+3),A	;
	LD	A,13H			; "P"
	LD	(DISPLAYBUF+7),A	; STORE IN DISP 7
	LD	A,14H			; "O"
	LD	(DISPLAYBUF+6),A	; STORE IN DISP 6
	LD	HL,DISPLAYBUF		; SET POINTER TO DISPLAY BUFFER
	CALL	HEXDISPLAY		; DISPLAY BUFFER CONTENTS
PORTREADGETKEY:
	CALL	KB_GET			; Get Key from KB
	CP	12H			; [cl] PRESSED, EXIT
	JP	Z,PortReadExit		;
	CP	10H			; [PR] PRESSED, PROMPT FOR NEW PORT
	JR	Z,DoPortRead		;
	JR	PORTREADGETKEY		; NO VALID KEY, LOOP
PortReadExit:
	LD	HL,CPUUP		; SET POINTER TO DATA BUFFER
	CALL	SEGDISPLAY		; DISPLAY 
	JP	FRONTPANELLoop		;

;__DoPortWrite____________________________________________________________________________________________________________________ 
;
;	PERFORM PORT WRITE FRONT PANEL ACTION
;________________________________________________________________________________________________________________________________
;
DoPortWrite:	
	CALL 	GETPORT			; GET PORT INTO A
PORTWRITELOOP:
	LD	C,A			; STORE PORT IN "C"
	SRL	A			; ROTATE HIGH NIB INTO LOW
	SRL	A			;
	SRL	A			;
	SRL	A			;
	LD	(DISPLAYBUF+5),A	; DISPLAY HIGH NIB IN DISPLAY 5
	LD	A,C			; RESTORE PORT VALUE INTO "A"
	AND	0FH			; CLEAR OUT HIGH NIB
	LD	(DISPLAYBUF+4),A	; DISPLAY LOW NIB IN DISPLAY 4
	LD	A,10H			; CLEAR OUT DISPLAYS 2 AND 3
	LD	(DISPLAYBUF+2),A	;
	LD	(DISPLAYBUF+3),A	;
	LD	A,13H			; DISPLAY "P" IN DISP 7
	LD	(DISPLAYBUF+7),A	;
	LD	A,14H			; DISPLAY "O" IN DISP 6
	LD	(DISPLAYBUF+6),A	;
	LD	HL,DISPLAYBUF		; POINT TO DISPLAY BUFFER
	CALL	GETVALUE		; INPUT A BYTE VALUE, RETURN IN "A"
	OUT	(C),A			; OUTPUT VALUE TO PORT STORED IN "C"
	LD	HL,CPUUP		; SET POINTER TO DATA BUFFER
	CALL	SEGDISPLAY		; DISPLAY 
	JP	FRONTPANELLoop		;


;__DoGo__________________________________________________________________________________________________________________________ 
;
;	PERFORM GO FRONT PANEL ACTION
;________________________________________________________________________________________________________________________________
;
DoGo:
	CALL 	GETADDR			; GET ADDRESS INTO HL
	JP	(HL)			; GO THERE!



;__DoDeposit________________________________________________________________________________________________________________________ 
;
;	PERFORM DEPOSIT FRONT PANEL ACTION
;________________________________________________________________________________________________________________________________
;
DoDeposit:
	CALL 	GETADDR			; GET ADDRESS INTO HL
	PUSH 	HL
DEPOSITLOOP:
	LD	A,H			;
	SRL	A			;
	SRL	A			;
	SRL	A			;
	SRL	A			;
	LD	(DISPLAYBUF+7),A	;
	LD	A,H			;
	AND	0FH			;
	LD	(DISPLAYBUF+6),A	;
	LD	A,L			;
	SRL	A			;
	SRL	A			;
	SRL	A			;
	SRL	A			;
	LD	(DISPLAYBUF+5),A	;
	LD	A,L			;
	AND	0FH			;
	LD	(DISPLAYBUF+4),A	;
	LD	A,10H			;
	LD	(DISPLAYBUF+3),A	;
	LD	HL,DISPLAYBUF		;
	CALL	GETVALUE		;
	POP	HL			;
	LD	(HL),A			;
DEPOSITGETKEY:
	CALL	KB_GET			; Get Key from KB
	CP	12H			; [cl] PRESSED, EXIT
	JP	Z,DepositExit		;
	CP	13H			; [EN] PRESSED, INC ADDRESS AND LOOP
	JR	Z,DEPOSITFW		; 
	CP	14H			; [DE] PRESSED, PROMPT FOR NEW ADDRESS
	JR	Z,DoDeposit		;
	JR	DEPOSITGETKEY		; NO VALID KEY, LOOP
DEPOSITFW:
	INC	HL			;
	PUSH	HL			; STORE HL
	JR 	DEPOSITLOOP		;	
DepositExit:
	LD	HL,CPUUP		; SET POINTER TO DATA BUFFER
	CALL	SEGDISPLAY		; DISPLAY 
	JP	FRONTPANELLoop		;




;__DoExamine________________________________________________________________________________________________________________________ 
;
;	PERFORM EXAMINE FRONT PANEL ACTION
;________________________________________________________________________________________________________________________________
;
DoExamine:
	CALL 	GETADDR			; GET ADDRESS INTO HL
	PUSH 	HL			; STORE HL
EXAMINELOOP:
	LD	A,H			; MOVE HIGH BYTE IN "A"
	SRL	A			; SHOW HIGH NIBBLE IN DISP 7
	SRL	A			;
	SRL	A			;
	SRL	A			;
	LD	(DISPLAYBUF+7),A	;
	LD	A,H			; RESTORE HIGH BYTE
	AND	0FH			; CLEAR HIGH NIBBLE
	LD	(DISPLAYBUF+6),A	; DISPLAY LOW NIBBLE IN DISP 6
	LD	A,L			; PUT LOW BYTE IN "A"
	SRL	A			; SHOW HIGH NIBBLE IN DISP 5
	SRL	A			;
	SRL	A			;
	SRL	A			;
	LD	(DISPLAYBUF+5),A	;
	LD	A,L			; RESTORE LOW BYTE IN "A"
	AND	0FH			; CLEAR OUT HIGH NIBBLE
	LD	(DISPLAYBUF+4),A	; DISPLAY LOW NIBBLE IN DISP 4
	LD	A,10H			; CLEAR OUT DISP 3
	LD	(DISPLAYBUF+3),A	;
	LD	A,(HL)			; GET VALUE FROM ADDRESS IN HL
	SRL	A			; DISPLAY HIGH NIB IN DISPLAY 1
	SRL	A			;
	SRL	A			;
	SRL	A			;
	LD	(DISPLAYBUF+1),A	;
	LD	A,(HL)			; GET VALUE FROM ADDRESS IN HL
	AND	0FH			; CLEAR OUT HIGH NIBBLE
	LD	(DISPLAYBUF),A		; DISPLAY LOW NIBBLE IN DISPLAY 0
	LD	HL,DISPLAYBUF		; POINT TO DISPLAY BUFFER
	CALL	HEXDISPLAY		; DISPLAY BUFFER ON DISPLAYS
	POP	HL			; RESTORE HL
EXAMINEGETKEY:
	CALL	KB_GET			; Get Key from KB
	CP	12H			; [cl] PRESSED, EXIT
	JP	Z,ExamineExit		;
	CP	13H			; [EN] PRESSED, INC ADDRESS AND LOOP
	JR	Z,EXAMINEFW		; 
	CP	15H			; [DE] PRESSED, PROMPT FOR NEW ADDRESS
	JR	Z,DoExamine		;
	JR	EXAMINEGETKEY		; NO VALID KEY, LOOP
EXAMINEFW:
	INC	HL			; HL++
	PUSH	HL			; STORE HL
	JR 	EXAMINELOOP		;	
ExamineExit:
	LD	HL,CPUUP		; SET POINTER TO DATA BUFFER
	CALL	SEGDISPLAY		; DISPLAY 
	JP	FRONTPANELLoop		;


;__GETADDR_______________________________________________________________________________________________________________________ 
;
;	GET ADDRESS FROM FRONT PANEL
;________________________________________________________________________________________________________________________________
;
GETADDR:
	PUSH	BC			; STORE BC
	JR	GETADDRCLEAR		; 
GETADDR1:
	LD	HL,ADDR			; DISPLAY PROMPT
	CALL	SEGDISPLAY		; 
GETADDRLOOP:
	CALL	KB_GET			;	
	CP	10H			;
	JP	M,GETADDRNUM		; NUMBER PRESSED, STORE IT
	CP	13H			; EN PRESSED, DONE
	JR	Z,GETADDRDONE		;
	CP	12H			; CLEAR PRESSED, CLEAR
	JR	Z,GETADDRCLEAR		; 
	JR	GETADDRLOOP		; INVALID KEY, LOOP
GETADDRDONE:
	LD	HL,00H			; HL=0
	LD	A,(DISPLAYBUF+1)	; GET DIGIT IN DISPLAY 1
	SLA	A			; ROTATE IT TO HIGH NIBBLE
	SLA	A			;
	SLA	A			;
	SLA	A			;
	LD	C,A			; STORE IT IN "C"	
	LD	A,(DISPLAYBUF)		; GET DIGIT IN DISPLAY 0
	AND	0FH			; CLEAR HIGH NIBBLE
	OR	C			; ADD IN NIBBLE STORED IN C
	LD	L,A			; STORE IT IN LOW BYTE OF ADDRESS POINTER
	LD	A,(DISPLAYBUF+3)	; GET DIGIT IN DISPLAY 3
	SLA	A			; ROTATE IT TO HIGH NIBBLE
	SLA	A			;
	SLA	A			;
	SLA	A			;
	LD	C,A			; STORE IT IN "C"	
	LD	A,(DISPLAYBUF+2)	; GET DIGIT IN DISPLAY 2
	AND	0FH			; CLEAR HIGH NIBBLE
	OR	C			; ADD IN NIBBLE STORED IN "C"
	LD	H,A			; STORE BYTE IN HIGH BYTE OF ADDRESS POINTER
	LD	A,10H			; CLEAR OUT DISPLAYS 0,1,2 & 3
	LD	(DISPLAYBUF),A		;
	LD	(DISPLAYBUF+1),A	;
	LD	(DISPLAYBUF+2),A	;
	LD	(DISPLAYBUF+3),A	;	
	POP	BC			; RESTORE BC	
	RET
GETADDRNUM:
	LD	C,A			;
	LD	A,(DISPLAYBUF+2)	; SHIFT BYTES IN DISPLAY BUF TO THE LEFT
	LD      (DISPLAYBUF+3),A	;
	LD	A,(DISPLAYBUF+1)	;	
	LD	(DISPLAYBUF+2),A	;
	LD	A,(DISPLAYBUF)		;	
	LD	(DISPLAYBUF+1),A	;
	LD	A,C			; DISPLAY KEYSTROKE IN RIGHT MOST DISPLAY (0)
	LD	(DISPLAYBUF+0),A	;
	JR	GETADDRDISP		;
GETADDRCLEAR:
	LD	A,12H			; CLEAR OUT DISPLAYS 0,1,2 & 3
	LD	(DISPLAYBUF),A		;
	LD	(DISPLAYBUF+1),A	;
	LD	(DISPLAYBUF+2),A	;
	LD	(DISPLAYBUF+3),A	;	
GETADDRDISP:
	LD	A,(DISPLAYBUF)		; ENCODE DIGITS IN DISPLAY BUFFER TO DISPLAY
	CALL 	DECODEDISPLAY		;
	LD	(ADDR),A		;
	LD	A,(DISPLAYBUF+1)	;
	CALL 	DECODEDISPLAY		;
	LD	(ADDR+1),A		;
	LD	A,(DISPLAYBUF+2)	;
	CALL 	DECODEDISPLAY		;
	LD	(ADDR+2),A		;
	LD	A,(DISPLAYBUF+3)	;
	CALL 	DECODEDISPLAY		;
	LD	(ADDR+3),A		;
	JP	GETADDR1		;



;__DSPSECTOR_______________________________________________________________________________________________________________________ 
;
;	DISPLAY SECTOR IN HL ON FRONT PANEL
;________________________________________________________________________________________________________________________________
;
DSPSECTOR:
	PUSH	BC			; STORE BC
	PUSH	HL			; STORE HL
	LD	A,H			; DISPLAY HIGH BYTE, HIGH NIBBLE
	SRL 	A			;	
	SRL 	A			;	
	SRL 	A			;	
	SRL 	A			;	
	AND	0FH			;
	CALL 	DECODEDISPLAY		;
	LD	(SEC+3),A		;
	LD      A,H			; DISPLAY HIGH BYTE, LOW NIBBLE
	AND	0FH			;
	CALL 	DECODEDISPLAY		;
	LD	(SEC+2),A		;
	LD	A,L			; DISPLAY LOW BYTE, HIGH NIBBLE
	AND	0F0H			;
	SRL 	A			;	
	SRL 	A			;	
	SRL 	A			;	
	SRL 	A			;		
	AND	0FH			;
	CALL 	DECODEDISPLAY		;
	LD	(SEC+1),A		; DISPLAY LOW BYTE, LOW NIBBLE
	LD      A,L			;
	AND	0FH			;
	CALL 	DECODEDISPLAY		;
	LD	(SEC),A			;
	LD	HL,SEC			; DISPLAY PROMPT
	CALL	SEGDISPLAY		; 
	POP	HL			; RESTORE HL
	POP	BC			; RESTORE BC
	RET



;__GETPORT_______________________________________________________________________________________________________________________ 
;
;	GET PORT FROM FRONT PANEL
;________________________________________________________________________________________________________________________________
;
GETPORT:
	PUSH	BC			; STORE BC
	JR	GETPORTCLEAR		;
GETPORT1:
	LD	HL,PORT			; DISPLAY PROMPT
	CALL	SEGDISPLAY		; 
GETPORTLOOP:
	CALL	KB_GET			;	
	CP	10H			;
	JP	M,GETPORTNUM		; NUMBER PRESSED, STORE IT
	CP	13H			; EN PRESSED, DONE
	JR	Z,GETPORTDONE		;
	CP	12H			; CLEAR PRESSED, CLEAR
	JR	Z,GETPORTCLEAR		; 
	JR	GETPORTLOOP		; INVALID KEY, LOOP
GETPORTDONE:
	LD	A,(DISPLAYBUF+1)	;
	SLA	A			;
	SLA	A			;
	SLA	A			;
	SLA	A			;
	LD	C,A			;	
	LD	A,(DISPLAYBUF)		;
	AND	0FH			;
	OR	C			;
	LD	C,A			;
	LD	A,10H			;
	LD	(DISPLAYBUF),A		;
	LD	(DISPLAYBUF+1),A	;
	LD	A,C			;
	POP	BC			; RESTORE BC	
	RET
GETPORTNUM:
	LD	C,A			;
	LD	A,(DISPLAYBUF)		;	
	LD	(DISPLAYBUF+1),A	;
	LD	A,C			;
	LD	(DISPLAYBUF+0),A	;
	JR	GETPORTDISP		;
GETPORTCLEAR:
	LD	A,12H			;
	LD	(DISPLAYBUF),A		;
	LD	(DISPLAYBUF+1),A	;
GETPORTDISP:
	LD	A,(DISPLAYBUF)		;
	CALL 	DECODEDISPLAY		;
	LD	(PORT),A		;
	LD	A,(DISPLAYBUF+1)	;
	CALL 	DECODEDISPLAY		;
	LD	(PORT+1),A		;
	JP	GETPORT1		;


;__GETVALUE______________________________________________________________________________________________________________________ 
;
;	GET VALUE FROM FRONT PANEL
;________________________________________________________________________________________________________________________________
;
GETVALUE:
	PUSH	BC			; STORE BC
	JR	GETVALUECLEAR		;
GETVALUE1:
	CALL	HEXDISPLAY		; 
	
GETVALUELOOP:
	CALL	KB_GET			;	
	CP	10H			;
	JP	M,GETVALUENUM		; NUMBER PRESSED, STORE IT
	CP	13H			; EN PRESSED, DONE
	JR	Z,GETVALUEDONE		;
	CP	12H			; CLEAR PRESSED, CLEAR
	JR	Z,GETVALUECLEAR		; 
	JR	GETVALUELOOP		; INVALID KEY, LOOP
GETVALUEDONE:
	LD	A,(DISPLAYBUF+1)	;
	SLA	A			;
	SLA	A			;
	SLA	A			;
	SLA	A			;
	LD	C,A			;	
	LD	A,(DISPLAYBUF)		;
	AND	0FH			;
	OR	C			;
        LD	C,A			;
	LD	A,10H			;
	LD	(DISPLAYBUF),A		;
	LD	(DISPLAYBUF+1),A	;
	LD	A,C			;
	POP	BC			; RESTORE BC		
	RET
GETVALUENUM:
	LD	C,A			;
	LD	A,(DISPLAYBUF)		;	
	LD	(DISPLAYBUF+1),A	;
	LD	A,C			;
	LD	(DISPLAYBUF+0),A	;
	JR	GETVALUE1		;
GETVALUECLEAR:
	LD	A,12H			;
	LD	(DISPLAYBUF),A		;
	LD	(DISPLAYBUF+1),A	;
	JP	GETVALUE1		;


;__MONSTARTWARM___________________________________________________________________________________________________________________ 
;
;	Serial Monitor Startup
;________________________________________________________________________________________________________________________________
;

MONSTARTWARM:				; CALL HERE FOR SERIAL MONITOR WARM START

	XOR	A			;ZERO OUT ACCUMULATOR (added)
	PUSH	HL			;protect HL from overwrite     
	LD	HL,TXT_READY		;POINT AT TEXT
	CALL	MSG			;SHOW WE'RE HERE
	POP	HL			;protect HL from overwrite

;
;__SERIAL_Monitor_Commands_________________________________________________________________________________________________________ 
;
; B Xx BOOT CPM FROM DRIVE Xx
; D XXXXH YYYYH  DUMP MEMORY FROM XXXX TO YYYY
; F XXXXH YYYYH ZZH FILL MEMORY FROM XXXX TO YYYY WITH ZZ
; H LOAD INTEL HEX FORMAT DATA
; I INPUT FROM PORT AND SHOW HEX DATA
; K ECHO KEYBOARD INPUT
; M XXXXH YYYYH ZZZZH MOVE MEMORY BLOCK XXXX TO YYYY TO ZZZZ
; O OUTPUT TO PORT HEX DATA
; P XXXXH YYH PROGRAM RAM FROM XXXXH WITH VALUE IN YYH, WILL PROMPT FOR NEXT LINES FOLLOWING UNTIL CR
; R RUN A PROGRAM FROM CURRENT LOCATION



;__Command_Parse_________________________________________________________________________________________________________________ 
;
;	Prompt User for commands, then parse them
;________________________________________________________________________________________________________________________________
;

SERIALCMDLOOP:
	CALL	CRLFA			; CR,LF,>
	LD	HL,KEYBUF		; SET POINTER TO KEYBUF AREA
	CALL 	GETLN			; GET A LINE OF INPUT FROM THE USER
	LD	HL,KEYBUF		; RESET POINTER TO START OF KEYBUF
        LD      A,(HL)			; LOAD FIRST CHAR INTO A (THIS SHOULD BE THE COMMAND)
	INC	HL			; INC POINTER

	CP	'B'			; IS IT "B" (Y/N)
	JP	Z,CONDOBOOT		; IF YES DO BOOT
	CP	'R'			; IS IT "R" (y/n)
	JP	Z,RUN			; IF YES GO RUN ROUTINE
	CP	'P'			; IS IT "P" (y/n)
	JP	Z,PROGRM		; IF YES GO PROGRAM ROUTINE
	CP	'O'			; IS IT AN "O" (y/n)
	JP	Z,POUT			; PORT OUTPUT
	CP	'H'			; IS IT A "H" (y/n)
	JP	Z,HXLOAD		; INTEL HEX FORMAT LOAD DATA
	CP	'I'			; IS IT AN "I" (y/n)
	JP	Z,PIN			; PORT INPUT
	CP	'D'			; IS IT A "D" (y/n)
	JP	Z,DUMP			; DUMP MEMORY
	CP	'K'
	JP	Z,KLOP			; LOOP ON KEYBOARD
	CP	'M'			; IS IT A "M" (y/n)
	JP	Z,MOVE			; MOVE MEMORY COMMAND
	CP	'F'			; IS IT A "F" (y/n)
	JP	Z,FILL			; FILL MEMORY COMMAND
	LD	HL,TXT_COMMAND		; POINT AT ERROR TEXT
	CALL	MSG			; print command label

	JR	SERIALCMDLOOP





;__KLOP__________________________________________________________________________________________________________________________ 
;
;	Read from the Serial Port and Echo, Monitor Command "K"
;________________________________________________________________________________________________________________________________
;
KLOP:
	CALL	KIN			; GET A KEY
	CALL	COUT			; OUTPUT KEY TO SCREEN
	CP	ESC			; IS <ESC>?
	JR	NZ,KLOP			; NO, LOOP
	JP	SERIALCMDLOOP		;

;__GETLN_________________________________________________________________________________________________________________________ 
;
;	Read a line(80) of text from the Serial Port, handle <BS>, term on <CR>.
;       Exit if too many chars.   Store result in HL.  Char count in C.
;________________________________________________________________________________________________________________________________
;
GETLN:
	LD	C,00H			; ZERO CHAR COUNTER
	PUSH	DE			; STORE DE
GETLNLOP:
	CALL	KIN			; GET A KEY
	CALL	COUT			; OUTPUT KEY TO SCREEN
	CP	CR			; IS <CR>?
	JR	Z,GETLNDONE		; YES, EXIT 
	CP	BS			; IS <BS>?
	JR	NZ,GETLNSTORE		; NO, STORE CHAR
	LD	A,C			; A=C
	CP	0			;
	JR	Z,GETLNLOP		; NOTHING TO BACKSPACE, IGNORE & GET NEXT KEY
	DEC	HL			; PERFORM BACKSPACE
	DEC	C			; LOWER CHAR COUNTER	
	LD	A,0			;
	LD	(HL),A			; STORE NULL IN BUFFER
	LD	A,20H			; BLANK OUT CHAR ON TERM
	CALL	COUT			;
	LD	A,BS			;
	CALL	COUT			;
	JR	GETLNLOP		; GET NEXT KEY
GETLNSTORE:
	LD	(HL),A			; STORE CHAR IN BUFFER
	INC	HL			; INC POINTER
	INC	C			; INC CHAR COUNTER	
	LD	A,C			; A=C
	CP	4DH			; OUT OF BUFFER SPACE?
	JR	NZ,GETLNLOP		; NOPE, GET NEXT CHAR
GETLNDONE:
	LD	(HL),00H		; STORE NULL IN BUFFER
	POP	DE			; RESTORE DE
	RET				;


;__KIN___________________________________________________________________________________________________________________________ 
;
;	Read from the Serial Port and Echo & convert input to UCASE
;________________________________________________________________________________________________________________________________
;
KIN:
	IN	A,(UART5)		; READ Line Status Register
	BIT	0,A			; TEST IF DATA IN RECEIVE BUFFER
	JP	Z,KIN			; LOOP UNTIL DATA IS READY
	IN	A,(UART0)		; THEN READ THE CHAR FROM THE UART
	AND	7FH			; STRIP HI BIT
	CP	'a'			; KEEP NUMBERS, CONTROLS
	RET	C			; AND UPPER CASE
	CP	7BH			; SEE IF NOT LOWER CASE
	RET	NC			; 
	AND	5FH			; MAKE UPPER CASE
	RET


;__COUT__________________________________________________________________________________________________________________________ 
;
;	Write the Value in "A" to the Serial Port
;________________________________________________________________________________________________________________________________
;
COUT:
	PUSH   AF			; Store AF
TX_BUSYLP:
	IN	A,(UART5)		; READ Line Status Register
	BIT	5,A			; TEST IF UART IS READY TO SEND
	JP	Z,TX_BUSYLP		; IF NOT REPEAT
	POP	AF			; Restore AF
	OUT	(UART0),A		; THEN WRITE THE CHAR TO UART
	RET				; DONE


;__CRLF__________________________________________________________________________________________________________________________ 
;
;	Send CR & LF to the Serial Port
;________________________________________________________________________________________________________________________________
;
CRLF:
	PUSH	HL			; protect HL from overwrite
	LD	HL,TCRLF		; Load Message Pointer
	CALL	MSG			; Sebd Message to Serial Port
	POP	HL			; protect HL from overwrite
	RET				;


;__LDHL__________________________________________________________________________________________________________________________ 
;
;	GET ONE WORD OF HEX DATA FROM BUFFER POINTED TO BY HL SERIAL PORT, RETURN IN HL
;________________________________________________________________________________________________________________________________
;
LDHL:
	PUSH	DE			; STORE DE
	CALL	HEXIN			; GET K.B. AND MAKE HEX
	LD	D,A			; THATS THE HI BYTE
	CALL	HEXIN			; DO HEX AGAIN
	LD	L,A			; THATS THE LOW BYTE
	LD	H,D			; MOVE TO HL
	POP	DE			; RESTORE BC
	RET				; GO BACK WITH ADDRESS  


;__HEXIN__________________________________________________________________________________________________________________________ 
;
;	GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A
;________________________________________________________________________________________________________________________________
;
HEXIN:
	PUSH	BC			;SAVE BC REGS.
	CALL	NIBL			;DO A NIBBLE
	RLC	A			;MOVE FIRST BYTE UPPER NIBBLE  
	RLC	A			; 
	RLC	A			; 
	RLC	A			; 
	LD	B,A			; SAVE ROTATED BYTE
	CALL	NIBL			; DO NEXT NIBBLE
	ADD	A,B			; COMBINE NIBBLES IN ACC.
	POP	BC			; RESTORE BC
	RET				; DONE  
NIBL:
	LD	A,(HL)			; GET K.B. DATA
	INC	HL			; INC KB POINTER
	CP	40H			; TEST FOR ALPHA
	JR	NC,ALPH			;
	AND	0FH			; GET THE BITS
	RET				;
ALPH:
	AND	0FH			; GET THE BITS
	ADD	A,09H			; MAKE IT HEX A-F
	RET				;


;__HEXINS_________________________________________________________________________________________________________________________ 
;
;	GET ONE BYTE OF HEX DATA FROM SERIAL PORT, RETURN IN A
;________________________________________________________________________________________________________________________________
;
HEXINS:
	PUSH	BC			;SAVE BC REGS.
	CALL	NIBLS			;DO A NIBBLE
	RLC	A			;MOVE FIRST BYTE UPPER NIBBLE  
	RLC	A			; 
	RLC	A			; 
	RLC	A			; 
	LD	B,A			; SAVE ROTATED BYTE
	CALL	NIBLS			; DO NEXT NIBBLE
	ADD	A,B			; COMBINE NIBBLES IN ACC.
	POP	BC			; RESTORE BC
	RET				; DONE  
NIBLS:
	CALL	KIN			; GET K.B. DATA
	INC	HL			; INC KB POINTER
	CP	40H			; TEST FOR ALPHA
	JR	NC,ALPH			;
	AND	0FH			; GET THE BITS
	RET				;


;__HXOUT_________________________________________________________________________________________________________________________ 
;
;	PRINT THE ACCUMULATOR CONTENTS AS HEX DATA ON THE SERIAL PORT
;________________________________________________________________________________________________________________________________
;
HXOUT:
	PUSH	BC			; SAVE BC
	LD	B,A			;
	RLC	A			; DO HIGH NIBBLE FIRST  
	RLC	A			;
	RLC	A			;
	RLC	A			;
	AND	0FH			; ONLY THIS NOW
	ADD	A,30H			; TRY A NUMBER
	CP	3AH			; TEST IT
	JR	C,OUT1			; IF CY SET PRINT 'NUMBER'
	ADD	A,07H			; MAKE IT AN ALPHA
OUT1:
	CALL	COUT			; SCREEN IT
	LD	A,B			; NEXT NIBBLE
	AND	0FH			; JUST THIS
	ADD	A,30H			; TRY A NUMBER
	CP	3AH			; TEST IT
	JR	C,OUT2			; PRINT 'NUMBER'
	ADD	A,07H			; MAKE IT ALPHA
OUT2:
	CALL	COUT			; SCREEN IT
	POP	BC			; RESTORE BC
	RET				;


;__SPACE_________________________________________________________________________________________________________________________ 
;
;	PRINT A SPACE CHARACTER ON THE SERIAL PORT
;________________________________________________________________________________________________________________________________
;
SPACE:
	PUSH	AF			; Store AF
	LD	A,20H			; LOAD A "SPACE"
	CALL	COUT			; SCREEN IT
	POP	AF			; RESTORE AF
	RET				; DONE

;__PHL_________________________________________________________________________________________________________________________ 
;
;	PRINT THE HL REG ON THE SERIAL PORT
;________________________________________________________________________________________________________________________________
;
PHL:
	LD	A,H			; GET HI BYTE
	CALL	HXOUT			; DO HEX OUT ROUTINE
	LD	A,L			; GET LOW BYTE
	CALL	HXOUT			; HEX IT
	CALL	SPACE			; 
	RET				; DONE  

;__POUT__________________________________________________________________________________________________________________________ 
;
;	Output to an I/O Port, Monitor Command "O"
;________________________________________________________________________________________________________________________________
;
POUT:
POUT1:
	INC	HL			;
	CALL	HEXIN			; GET PORT
	LD	C,A			; SAVE PORT POINTER
	INC	HL			;
	CALL	HEXIN			; GET DATA
OUTIT:
	OUT	(C),A			;
	JP	SERIALCMDLOOP		;


;__PIN___________________________________________________________________________________________________________________________ 
;
;	Input From an I/O Port, Monitor Command "I"
;________________________________________________________________________________________________________________________________
;
PIN:
	INC 	HL			;
	CALL	HEXIN			; GET PORT
	LD	C,A			; SAVE PORT POINTER
	CALL	CRLF			;
	IN	A,(C)			; GET DATA
	CALL	HXOUT			; SHOW IT
	JP	SERIALCMDLOOP	        ;



;__cONDoBoot_____________________________________________________________________________________________________________________ 
;
;	PERFORM BOOT ACTION
;________________________________________________________________________________________________________________________________
;
CONDOBOOT:
	INC 	HL			;
	CALL	HEXIN			; GET BOOT SEQ
	LD	C,A			; SAVE PORT POINTER
	CALL	CRLF			;
	LD	A,C			;
	CP	01H			; [1] PRESSED, BOOT ROM CP/M
	JP	Z,GOCPM			;
	CP	02H			; [2] PRESSED, BOOT ATAPI PRIMARY
	JP	Z,CONBOOTATAPIPRI	; 
	CP	03H			; [3] PRESSED, BOOT ATAPI SECONDARY
	JP	Z,CONBOOTATAPISEC	;
	JP	SERIALCMDLOOP	        ;

CONBOOTATAPIPRI:
	LD	A,00H
	LD	(IDEDEVICE),A		; SET PRIMARY DEVICE
	JR	CONBOOTATAPI		;
CONBOOTATAPISEC:
	LD	A,10H			;
	LD	(IDEDEVICE),A		; SET SECONDARY DEVICE
CONBOOTATAPI:
	CALL	IDE_SOFT_RESET		;
	LD	DE,0000H		; SET SECTOR HIGH WORD TO 00H
	LD	HL,0000H		; SET SECTOR LOW WORD TO 00H
	LD	IX,0D400H		; SET TOP OF CP/M
	LD	B,21			; SET NUMBER OF SECTORS TO LOAD
CONBOOTATAPILOOP:
	CALL	ATAPI_READ_SECTOR	; READ A SECTOR
	INC	HL			; POINT TO NEXT SECTOR
	DJNZ	CONBOOTATAPILOOP	; LOOP
	JP	0EA00H			; GO TO CP/M



;__CRLFA_________________________________________________________________________________________________________________________ 
;
;	Print Command Prompt to the serial port
;________________________________________________________________________________________________________________________________
;
CRLFA:
	PUSH	HL			; protect HL from overwrite
	LD	HL,PROMPT		;
	CALL	MSG			;
	POP	HL			; protect HL from overwrite
	RET				; DONE


;__MSG___________________________________________________________________________________________________________________________ 
;
;	Print a String  to the serial port
;________________________________________________________________________________________________________________________________
;
MSG:

TX_SERLP:
	LD	A,(HL)			; GET CHARACTER TO A
	CP	END			; TEST FOR END BYTE
	JP	Z,TX_END		; JUMP IF END BYTE IS FOUND
	CALL	COUT			;
	INC	HL			; INC POINTER, TO NEXT CHAR
	JP	TX_SERLP		; TRANSMIT LOOP
TX_END:
	RET				;ELSE DONE

;__RUN___________________________________________________________________________________________________________________________ 
;
;	TRANSFER OUT OF MONITOR, User option "R"
;________________________________________________________________________________________________________________________________
;
RUN:
	INC	HL			; SHOW READY
	CALL	LDHL			; GET START ADDRESS
	JP	(HL)			;	


;__PROGRM________________________________________________________________________________________________________________________ 
;
;	Program RAM locations, User option "P"
;________________________________________________________________________________________________________________________________
;
PROGRM:
	INC	HL			; SHOW READY
	PUSH	HL			; STORE HL
	CALL	LDHL			; GET START ADDRESS
	LD	D,H			;
	LD	E,L			; DE POINTS TO ADDRESS TO PROGRAM
	POP	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
PROGRMLP:
	CALL	HEXIN			; GET NEXT HEX NUMBER
	LD	(DE),A			; STORE IT
	INC	DE			; NEXT ADDRESS;
	CALL	CRLFA			; CR,LF,>
	LD      A,'P'			;
	CALL	COUT			;
	CALL  	SPACE			;
	LD	H,D			;
	LD	L,E			;
	CALL	PHL			;
	LD	HL,KEYBUF		; SET POINTER TO KEYBUF AREA
	CALL 	GETLN			; GET A LINE OF INPUT FROM THE USER
	LD	HL,KEYBUF		; RESET POINTER TO START OF KEYBUF
        LD      A,(HL)			; LOAD FIRST CHAR INTO A 
	CP	00H			; END OF LINE?
	JP	Z,PROGRMEXIT		; YES, EXIT
	JP	PROGRMLP		; NO, LOOP
PROGRMEXIT:
	JP	SERIALCMDLOOP	







;__DUMP__________________________________________________________________________________________________________________________ 
;
;	Print a Memory Dump, User option "D"
;________________________________________________________________________________________________________________________________
;
DUMP:
	INC	HL			; SHOW READY
	PUSH	HL			; STORE HL
	CALL	LDHL			; GET START ADDRESS
	LD	D,H			;
	LD	E,L			;
	POP	HL			;
	PUSH	DE			; SAVE START
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
	CALL	LDHL			; GET END ADDRESS
	INC	HL			; ADD ONE MORE FOR LATER COMPARE
	EX	DE,HL			; PUT END ADDRESS IN DE
	POP	HL			; GET BACK START
GDATA:	
	CALL	CRLF			;	
BLKRD:
	CALL	PHL			; PRINT START LOCATION
	LD	C,16			; SET FOR 16 LOCS
	PUSH	HL			; SAVE STARTING HL
NXTONE:
	EXX				;
	LD	C,E			;
	IN	A,(C)			;
	EXX				;
	AND	7FH			;
	CP	ESC			;
	JP	Z,SERIALCMDLOOP		;
	CP	19			;
	JR	Z,NXTONE		;
	LD 	A,(HL)			; GET BYTE
	CALL	HXOUT			; PRINT IT
	CALL	SPACE			;
UPDH:	
	INC	HL			; POINT NEXT
	DEC	C			; DEC. LOC COUNT
	JR	NZ,NXTONE		; IF LINE NOT DONE
					; NOW PRINT 'DECODED' DATA TO RIGHT OF DUMP
PCRLF:
	CALL	SPACE			; SPACE IT
	LD	C,16			; SET FOR 16 CHARS
	POP	HL			; GET BACK START
PCRLF0:
	LD	A,(HL)			; GET BYTE
	AND	060H			; SEE IF A 'DOT'
	LD	A,(HL)			; O.K. TO GET
	JR	NZ,PDOT			;
DOT:
	LD	A,2EH			; LOAD A DOT	
PDOT:
	CALL	COUT			; PRINT IT
	INC	HL			; 
	LD	A,D			;
	CP	H			;
	JR	NZ,UPDH1		;
	LD	A,E			;
	CP	L			;
	JP	Z,SERIALCMDLOOP		;
;
;IF BLOCK NOT DUMPED, DO NEXT CHARACTER OR LINE
UPDH1:
	DEC	C			; DEC. CHAR COUNT
	JR	NZ,PCRLF0		; DO NEXT
CONTD:
	CALL	CRLF			;
	JP	BLKRD			;


;__HXLOAD__________________________________________________________________________________________________________________________ 
;
;	LOAD INTEL HEX FORMAT FILE FROM THE SERIAL PORT, User option "H"
;
;	 [INTEL HEX FORMAT IS:
;	 1) COLON (FRAME 0)
;	 2) RECORD LENGTH FIELD (FRAMES 1 AND 2)
;	 3) LOAD ADDRESS FIELD (FRAMES 3,4,5,6)
;	 4) RECORD TYPE FIELD (FRAMES 7 AND 8)
;	 5) DATA FIELD (FRAMES 9 TO 9+2*(RECORD LENGTH)-1
;	 6) CHECKSUM FIELD - SUM OF ALL BYTE VALUES FROM RECORD LENGTH TO AND 
;	   INCLUDING CHECKSUM FIELD = 0 ]
;
; EXAMPLE OF INTEL HEX FORMAT FILE
; EACH LINE CONTAINS A CARRIAGE RETURN AS THE LAST CHARACTER
; :18F900002048454C4C4F20574F524C4420FF0D0AFF0D0A3EFF0D0A54BF
; :18F918006573742050726F746F7479706520524F4D204D6F6E69746FF1
; :18F9300072205265616479200D0AFF0D0A434F4D4D414E4420524543F2
; :18F948004549564544203AFF0D0A434845434B53554D204552524F52CD
; :16F96000FF0A0D20202D454E442D4F462D46494C452D20200A0DA4
; :00000001FF
;________________________________________________________________________________________________________________________________
HXLOAD:
	CALL	CRLF			; SHOW READY
HXLOAD0:
	CALL	KIN			; GET THE FIRST CHARACTER, EXPECTING A ':'
HXLOAD1:
	CP	$3A			; IS IT COLON ':'? START OF LINE OF INTEL HEX FILE
	JR	NZ,HXLOADERR		; IF NOT, MUST BE ERROR, ABORT ROUTINE
	LD	E,0			; FIRST TWO CHARACTERS IS THE RECORD LENGTH FIELD
	CALL	HEXINS			; GET US TWO CHARACTERS INTO BC, CONVERT IT TO A BYTE <A>
	CALL	HXCHKSUM		; UPDATE HEX CHECK SUM
	LD	D,A			; LOAD RECORD LENGTH COUNT INTO D
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, MEMORY LOAD ADDRESS <H>
	CALL	HXCHKSUM		; UPDATE HEX CHECK SUM
	LD	H,A			; PUT VALUE IN H REGISTER.
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, MEMORY LOAD ADDRESS <L>
	CALL	HXCHKSUM		; UPDATE HEX CHECK SUM
	LD	L,A			; PUT VALUE IN L REGISTER.
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, RECORD FIELD TYPE
	CALL	HXCHKSUM		; UPDATE HEX CHECK SUM
	CP	$01			; RECORD FIELD TYPE 00 IS DATA, 01 IS END OF FILE
	JR	NZ,HXLOAD2		; MUST BE THE END OF THAT FILE
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, ASSEMBLE INTO BYTE
	CALL	HXCHKSUM		; UPDATE HEX CHECK SUM
	LD	A,E			; RECALL THE CHECKSUM BYTE
	AND	A			; IS IT ZERO?
        JP      Z,HXLOADEXIT		; MUST BE O.K., GO BACK FOR SOME MORE, ELSE
	JR	HXLOADERR		; CHECKSUMS DON'T ADD UP, ERROR OUT	
HXLOAD2:
	LD	A,D			; RETRIEVE LINE CHARACTER COUNTER	
	AND	A			; ARE WE DONE WITH THIS LINE?
	JR	Z,HXLOAD3		; GET TWO MORE ASCII CHARACTERS, BUILD A BYTE AND CHECKSUM
	CALL	HEXINS			; GET NEXT TWO CHARS, CONVERT TO BYTE IN A, CHECKSUM IT
	CALL	HXCHKSUM		; UPDATE HEX CHECK SUM
	LD	(HL),A			; CHECKSUM OK, MOVE CONVERTED BYTE IN A TO MEMORY LOCATION
	INC	HL			; INCREMENT POINTER TO NEXT MEMORY LOCATION	
	DEC	D			; DECREMENT LINE CHARACTER COUNTER
	JR	HXLOAD2			; AND KEEP LOADING INTO MEMORY UNTIL LINE IS COMPLETE		
HXLOAD3:
	CALL	HEXINS			; GET TWO CHARS, BUILD BYTE AND CHECKSUM
	CALL	HXCHKSUM		; UPDATE HEX CHECK SUM
	LD	A,E			; CHECK THE CHECKSUM VALUE
	AND	A			; IS IT ZERO?
	JR	Z,HXLOADAGAIN		; IF THE CHECKSUM IS STILL OK, CONTINUE ON, ELSE
HXLOADERR:
	LD	HL,TXT_CKSUMERR		; GET "CHECKSUM ERROR" MESSAGE
	CALL	MSG			; PRINT MESSAGE FROM (HL) AND TERMINATE THE LOAD
	JP	HXLOADEXIT		; RETURN TO PROMPT
HXCHKSUM:
	LD	C,A			; BUILD THE CHECKSUM
	LD	A,E			;
	SUB	C			; THE CHECKSUM SHOULD ALWAYS EQUAL ZERO WHEN CHECKED
	LD	E,A			; SAVE THE CHECKSUM BACK WHERE IT CAME FROM
	LD	A,C			; RETRIEVE THE BYTE AND GO BACK
	RET				; BACK TO CALLER
HXLOADAGAIN:
	CALL	KIN			; CATCH THE TRAILING CARRIAGE RETURN
	JP	HXLOAD0			; LOAD ANOTHER LINE OF DATA
HXLOADEXIT:
	CALL	KIN			; CATCH ANY STRAY TRAILING CHARACTERS
	JP	SERIALCMDLOOP		; RETURN TO PROMPT


;__MOVE__________________________________________________________________________________________________________________________ 
;
;	Move Memory, User option "M"
;________________________________________________________________________________________________________________________________
;
MOVE:
	LD	C,03
					; start GETNM replacement
					; get source starting memory location
	INC	HL			; SHOW EXAMINE READY
	PUSH	HL			;
	CALL	LDHL			; LOAD IN HL REGS.
	LD	D,H			;
	LD	E,L			;
	POP	HL			;
	PUSH	DE			; push memory address on stack
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC 	HL			; print space separator
	PUSH	HL			;
	CALL	LDHL			; LOAD IN HL REGS.
	LD	D,H			;
	LD	E,L			;
	POP	HL			;
	PUSH	DE			; push memory address on stack
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			; print space separator
	CALL	LDHL			; LOAD IN HL REGS.
	PUSH	HL			; push memory address on stack
					; end GETNM replacement
	POP	DE			; DEST
	POP	BC			; SOURCE END
	POP	HL			; SOURCE
	PUSH    HL			;
	LD	A,L			;
	CPL				;
	LD	L,A			;
	LD	A,H			;
	CPL				;
	LD	H,A			;
	INC	HL			;
	ADD	HL,BC			;
	LD	C,L			;
	LD	B,H			;
	POP     HL        		;
	CALL    MOVE_LOOP		;
	JP	SERIALCMDLOOP			; EXIT MOVE COMMAND ROUTINE
MOVE_LOOP:
	LD	A,(HL)			; FETCH
	LD	(DE),A			; DEPOSIT
	INC     HL			; BUMP  SOURCE
	INC     DE			; BUMP DEST
	DEC     BC			; DEC COUNT
	LD	A,C			;
	OR	B       		;
	JP	NZ,MOVE_LOOP		; TIL COUNT=0
	RET				;
               
;__FILL__________________________________________________________________________________________________________________________ 
;
;	Fill Memory, User option "M"
;________________________________________________________________________________________________________________________________
;
FILL:
	LD	C,03			;
					; start GETNM replacement
					; get fill starting memory location
	INC	HL			; SHOW EXAMINE READY
	PUSH	HL			;
	CALL	LDHL			; LOAD IN HL REGS.
	LD	D,H			;
	LD	E,L			;
	POP	HL			;
	PUSH	DE			; push memory address on stack
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			; print space separator
					; get fill ending memory location
	PUSH	HL			;
	CALL	LDHL			; LOAD IN HL REGS.
	LD	D,H			;
	LD	E,L			;
	POP	HL			;
	PUSH	DE			; push memory address on stack
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			;
	INC	HL			; print space separator
					; get target starting memory location
	CALL	HEXIN			; GET K.B. AND MAKE HEX
	LD	C,A			; put fill value in F so it is saved for later
	PUSH	BC			; push fill value byte on stack
					; end GETNM replacement
	POP	BC			; BYTE
	POP	DE			; END
	POP	HL			; START
	LD	(HL),C			;
FILL_LOOP:
	LD	(HL),C			;
	INC     HL			;
	LD	A,E			;
	SUB     L			;
	LD	B,A			;
	LD	A,D			;
	SUB     H			;
	OR	B			;
	JP	NZ,FILL_LOOP		;
	JP	SERIALCMDLOOP		;

;__GOCPM_________________________________________________________________________________________________________________________ 
;
;	BOOT CP/M From ROM Drive, User option "C"
;________________________________________________________________________________________________________________________________
;
GOCPM:
;___________________________
; REMOVE COMMENTS WHEN BURNED IN ROM
;___________________________

;	LD	A,%00000000		; RESET MPCL latch to default ROM
;	OUT	(MPCL),A		;
;	LD	HL,ROMSTART_CPM		; where in rom CP/M is stored (first byte)
;        LD	DE,RAMTARG_CPM		; where in ram to move Monitor to (first byte)
;	LD	BC,MOVSIZ_CPM		; number of bytes to move from ROM to RAM
;	LDIR				; Perform Block Copy of CP/M to Upper RAM page
;	LD	A,%10000000		; RESET MPCL latch to default CP/M with 64K setting
;	OUT	(MPCL),A		;

	JP	$EA00			; CP/M COLD BOOT ENTRY POINT

;
;__Init_UART_____________________________________________________________________________________________________________________ 
;
;	Initialize UART
;	Params:	SER_BAUD Needs to be set to Baud Rate
;	1200:	96	 = 1,843,200 / ( 16 x 1200 )
;	2400:	48	 = 1,843,200 / ( 16 x 2400 )
;	4800:	24	 = 1,843,200 / ( 16 x 4800 )
;	9600:	12	 = 1,843,200 / ( 16 x 9600 )
;	19K2:	06	 = 1,843,200 / ( 16 x 19,200 )
;	38K4:	03	
;	57K6:	02
;	115K2:	01	
;
;_________________________________________________________________________________________________________________________________
;
INIT_UART:
	LD	A,80H			;
	OUT	(UART3),A		; SET DLAB FLAG
	LD	A,(SER_BAUD)		;
	OUT	(UART0),A		;
	LD	A,00H			;
	OUT	(UART1),A		;
	LD	A,03H			;
	OUT	(UART3),A		; Set 8 bit data, 1 stopbit
	RET


;
;__FILL_MEM_______________________________________________________________________________________________________________________ 
;
;	Function	: fill memory with a value
;	Input		: HL = start address block
;			: BC = length of block
;			: A = value to fill with
;	Uses		: DE, BC
;	Output		:
;	calls		: 
;	tested		: 13 Feb 2007
;_________________________________________________________________________________________________________________________________
;
FILL_MEM:
	ld	e,l			;
	ld	d,h			;
	inc	de			;
	ld	(hl),A			; initialise first byte of block with data byte in A
	ldir				; fill memory
	RET				; return to caller

;
;__Initialize_____________________________________________________________________________________________________________________ 
;
;	Initialize System
;_________________________________________________________________________________________________________________________________
;
INITIALIZE:
	LD	A,12			; specify baud rate 9600 bps (9600,8,None,1)
	LD	(SER_BAUD),A		; 
	CALL	INIT_UART		; INIT the UART 
	RET	 			; 
;

;__mTerm_Init________________________________________________________________________________________
;
;  Setup 8255, Mode 0, Port A=Out, Port B=In, Port C=Out/Out 
;     
;____________________________________________________________________________________________________
mTerm_Init:
	LD	A, 82H
	OUT (PIOCONT),A
	RET

;__KB_GET____________________________________________________________________________________________
;
;  Get a Single Key and Decode
;     
;____________________________________________________________________________________________________
KB_GET:
	PUSH 	HL			; STORE HL
KB_Get_Loop:				; WAIT FOR KEY
	CALL	KB_Scan			;  Scan KB Once
	CP	00H			;  Null?
	JR	Z,KB_Get_Loop		;  Loop while not zero
	LD      D,A			;  Store A
	LD	A,4FH			;  Scan All Col Lines
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
KB_Clear_Loop:				; WAIT FOR KEY TO CLEAR
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Clear_Loop	;  Yes, Exit.
	LD	A,D			;  Restore A
	LD	D,00H			;
	LD	HL,KB_Decode		;  Point to beginning of Table	
KB_Get_LLoop:
	CP	(HL)			;  Match?	
	JR	Z,KB_Get_Done		;  Found, Done
	INC	HL
	INC	D			;  D + 1	
	JP	NZ,KB_Get_LLoop		;  Not Found, Loop until EOT			
KB_Get_Done:
	LD	A,D			;  Result Into A
	POP	HL			; RESTORE HL
	RET



;__KB_Scan____________________________________________________________________________________________
;
;  SCan Keyboard Matrix for an input
;     
;____________________________________________________________________________________________________
KB_Scan:

	LD      C,0000H
	LD	A,41H			;  Scan Col One
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Scan_Found	;  Yes, Exit.

	LD      C,0040H
	LD	A,42H			;  Scan Col Two
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Scan_Found	;  Yes, Exit.

	LD      C,0080H
	LD	A,44H			;  Scan Col Three
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Scan_Found	;  Yes, Exit.

	LD      C,00C0H			;
	LD	A,48H			;  Scan Col Four
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Scan_Found	;  Yes, Exit.

	LD	A, 40H			;  Turn off All Columns
	OUT 	(PORTC),A		;  Send to Column Lines
	LD	A, 00H			;  RETURN NULL
	RET				;  Exit

KB_Scan_Found:
	AND	3FH			;  Clear Top two Bits
	OR	C			;  Add in Row Bits 
	LD	C,A			;  Store Value
	LD	A, 00H			;  Turn off All Columns
	OUT 	(PORTC),A		;  Send to Column Lines
	LD	A,C			;  Restore Value
	RET

PAUSE:
KB_Scan_Delay:
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	RET



;__HEXDISPLAY________________________________________________________________________________________
;
;  Display contents of DISPLAYBUF in decoded Hex bits 0-3 are displayed dig, bit 7 is DP
;     
;____________________________________________________________________________________________________
HEXDISPLAY:
	PUSH	HL			; STORE HL
	PUSH	AF			; STORE AF
	PUSH	BC			; STORE BC
	LD	BC,0007H	
	ADD	HL,BC
	LD	B,08H			; SET DIGIT COUNT
	LD	A,40H			; set Control port 7218 to off
	OUT	(PORTC),A		; output
	CALL 	PAUSE			; wait
	LD	A,0F0H			; set control to 1111 (Data Coming, Hex Decode,NO Decode, Normal)
	OUT	(PORTA),A		; output to port
	LD	A,80H			; Strobe write pulse with Control=1
	OUT	(PORTC),A		; output to port
	CALL 	PAUSE			; wait
	LD	A,40H			; set Control port 7218 to off
	OUT	(PORTC),A		; output
HEXDISPLAY_LP:		
	LD	A,(HL)			; GET DISPLAY DIGIT
	CALL	DECODEDISPLAY		; DECODE DISPLAY
	OUT	(PORTA),A		; OUT TO PORTA
	LD	A,00H			; SET WRITE STROBE
	OUT	(PORTC),A		; OUT TO PORTC
	CALL	PAUSE			; DELAY
	LD	A,40H			; SET CONTROL PORT OFF
	OUT	(PORTC),A		; OUT TO PORTC
	CALL	PAUSE			; WAIT
	DEC	HL			; INC POINTER
	DJNZ	HEXDISPLAY_LP		; LOOP FOR NEXT DIGIT
	POP	BC			; RESTORE BC
	POP	AF			; RESTORE AF
	POP	HL			; RESTORE HL
	RET

;__DECODEDISPLAY_____________________________________________________________________________________
;
;  Display contents of DISPLAYBUF in decoded Hex bits 0-3 are displayed dig, bit 7 is DP
;     
;____________________________________________________________________________________________________
DECODEDISPLAY:
	PUSH	BC			; STORE BC
	PUSH	HL			; STORE HL
	LD	HL,SEGDECODE		; POINT HL TO DECODE TABLE
	LD	B,00H			; RESET HIGH BYTE
	LD	C,A			; CHAR INTO LOW BYTE
	ADD	HL,BC			; SET TABLE POINTER
	LD	A,(HL)			; GET VALUE
	POP	HL			; RESTORE HL
	POP	BC			; RESTORE BC
	RET


;__SEGDISPLAY________________________________________________________________________________________
;
;  Display contents of DISPLAYBUF in decoded Hex bits 0-3 are displayed dig, bit 7 is DP
;     
;____________________________________________________________________________________________________
SEGDISPLAY:
	PUSH	AF			; STORE AF
	PUSH	BC			; STORE BC
	LD	BC,0007H	
	ADD	HL,BC
	LD	B,08H			; SET DIGIT COUNT
	LD	A,40H			; set Control port 7218 to off
	OUT	(PORTC),A		; output
	CALL 	PAUSE			; wait
	LD	A,0F0H			; set control to 1111 (Data Coming, Hex Decode,NO Decode, Normal)
	OUT	(PORTA),A		; output to port
	LD	A,80H			; Strobe write pulse with Control=1
	OUT	(PORTC),A		; output to port
	CALL 	PAUSE			; wait
	LD	A,40H			; set Control port 7218 to off
	OUT	(PORTC),A		; output
SEGDISPLAY_LP:		
	LD	A,(HL)			; GET DISPLAY DIGIT
	OUT	(PORTA),A		; OUT TO PORTA
	LD	A,00H			; SET WRITE STROBE
	OUT	(PORTC),A		; OUT TO PORTC
	CALL	PAUSE			; DELAY
	LD	A,40H			; SET CONTROL PORT OFF
	OUT	(PORTC),A		; OUT TO PORTC
	CALL	PAUSE			; WAIT
	DEC	HL			; INC POINTER
	DJNZ	SEGDISPLAY_LP		; LOOP FOR NEXT DIGIT
	POP	BC			; RESTORE BC
	POP	AF			; RESTORE AF
	RET
;________________________________________________________________________________________________________________________________ 
;
;   ATAPI Code
;________________________________________________________________________________________________________________________________ 

;__ATAPI_READ_SECTOR_____________________________________________________________________________________________________________ 
;  READ ATAPI SECTOR   
;
;   D E H L = SECTOR (DOUBLE WORD) TO READ 
;   IX = READ TO ADDRESS 
;
;   ON RETURN IX WILL BE POINTED TO NEXT BYTE AFTER READ OPERATION 
;________________________________________________________________________________________________________________________________ 
ATAPI_READ_SECTOR:
	PUSH	BC			; STORE BC
	PUSH	DE			; STORE DE
	PUSH	HL			; STORE HL
	LD	A,D			; STORE SECTOR ADDRESS TO PACKET
	LD	(READ_DISK_PACKET+2),A	;
	LD	A,E			;
	LD	(READ_DISK_PACKET+3),A	;
	LD	A,H			;
	LD	(READ_DISK_PACKET+4),A	;
	LD	A,L			;
	LD	(READ_DISK_PACKET+5),A	;
	CALL	REQUEST_SENSE_LOOP	; GET ATAPI SENSE CODES TO CLEAR ERRORS
	LD	HL,READ_DISK_PACKET	; SET POINTER TO READ SECTOR PACKET
	CALL	ATAPI_SEND_PACKET	; SEND PACKET COMMAND
	CALL	ATAPI_READ_DATA		; 
	POP	HL			; RESTORE HL
	POP	DE			; RESTORE DE
	POP	BC			; RESTORE BC
	RET				;



;__ATAPI_SEND_PACKET_____________________________________________________________________________________________________________ 
;  SEND PACKET POINTED TO BY HL TO ATAPI DRIVE   
;
;________________________________________________________________________________________________________________________________ 
ATAPI_SEND_PACKET:

	CALL	IDE_WAIT_BUSY_READY	; MAKE SURE DRIVE IS READY TO PROCEED
	CALL	IDE_WAIT_DRQ_ZERO	;
					;
	LD	A,0AH			;
	OUT	(IDECTRL),A		; Disable INT
	LD	A,00H			;
	OUT	(IDEERR),A		;
	LD	A,00H			;
	OUT	(IDESECTC),A		; 
	LD	A,00H			;
	OUT	(IDESECTN),A		;
	LD	A,00H			;
	OUT	(IDECYLLO),A		; 
	LD	A,60H			;
	OUT	(IDECYLHI),A		; 
	LD	A,(IDEDEVICE)		;
	OUT	(IDEHEAD),A		; Bit 4 selects device
	LD	A,0A0H			;
	OUT	(IDESTTS),A		;
					;
	CALL	IDE_WAIT_DRQ_READY	; MAKE SURE DRIVE IS READY TO PROCEED
					;
	LD	B,6			; SEND 12 BYTES (6 WORDS)
					;
ATAPI_SEND_PACKET_LOOP:
	LD	A,(HL)			; GET BYTE
	LD	D,A			; STORE LOW BYTE IN D
	INC	HL			; INC POINTER
	LD	A,(HL)			; GET HIGH BYTE
	OUT	(IDEHI),A		; STORE HIGH BYTE
	LD	A,D			; MOVE LOW BYTE INTO A
	OUT	(IDELO),A		; STORE LOW BYTE
	INC	HL			; INC POINTER
	IN	A,(IDECTRL)		; GET STATUS
	DJNZ	ATAPI_SEND_PACKET_LOOP	; LOOP
					;
	CALL	IDE_WAIT_BUSY_READY	; MAKE SURE DRIVE IS READY TO PROCEED
	IN	A,(IDECTRL)		; READ STATUS (FOR DELAY)
					;
	RET				;




;__ATAPI_READ_DATA__________________________________________________________________________________________________________
;      READ DATA BLOCK INTO IDE_SECTOR_BUFFER
;
; IX = POINTER TO BUFFER
;
;___________________________________________________________________________________________________________________________

ATAPI_READ_DATA:
	LD	B,0			; 256 WORDS (512 BYTES PER SECTOR)
	CALL	IDE_WAIT_BUSY_READY	; MAKE SURE DRIVE IS READY TO PROCEED
	IN	A,(IDESTTS)		; READ  REG
	AND	%00001000		; MASK OFF BIT
	CP	08H			; IS DATA WAITING?
	JR	NZ,ATAPI_READ_DATA_EXIT	; NO, EXIT
ATAPI_READ_DATA_LOOP:
	IN	A,(IDELO)		;
	LD	(IX),A			;
	INC	IX			;
	IN	A,(IDEHI)		;
	LD	(IX),A			;
	INC	IX			;
	DJNZ	ATAPI_READ_DATA_LOOP	;
ATAPI_READ_DATA_EXIT:
	RET				;

;__IDE_SOFT_RESET__________________________________________________________________________________________________________
;      RESET IDE DEVICE
;___________________________________________________________________________________________________________________________
IDE_SOFT_RESET:

	LD	A,%00001110		;NO INTERRUPTS, RESET DRIVE = 1
	OUT	(IDECTRL),A		;
	CALL	DELAY			;
	LD	A,%00001010		;NO INTERRUPTS, RESET DRIVE = 0
	OUT	(IDECTRL),A		;
	CALL	IDE_WAIT_BUSY_READY	;
	
	CALL	ATAPI_DEVICE_SELECTION	;
	CALL	DELAY			;
	CALL 	REQUEST_SENSE_LOOP	;
	RET

;__REQUEST_SENSE_LOOP_______________________________________________________________________________________________________
;      REQUEST SENSE DATA FROM DEVICE
;___________________________________________________________________________________________________________________________
REQUEST_SENSE_LOOP:
	PUSH	HL			; STORE HL
	PUSH	IX			; STORE IX
	PUSH	AF			; STORE AF
	LD	HL,ATAPI_REQUEST_SENSE	;
	CALL	ATAPI_SEND_PACKET	;
	LD	IX,IDE_SECTOR_BUFFER	; SET SECTOR BUFFER
	CALL	ATAPI_READ_DATA		;	
	CALL	DELAY			;
	IN	A,(IDESTTS)		;READ ERROR REG
	AND	%00000001		;MASK OFF BIT
	JR	NZ,REQUEST_SENSE_LOOP	;
	POP	AF			; RESTORE AF
	POP	IX			; RESTORE IX
	POP	HL			; RESTORE HL
	RET


;__ATAPI_DEVICE_SELECTION___________________________________________________________________________________________________
; IDE SELECT DEVICE 
;___________________________________________________________________________________________________________________________
ATAPI_DEVICE_SELECTION:

	CALL	IDE_WAIT_BUSY_READY	;	
	LD	A,(IDEDEVICE)		; Selects Device
	OR	0A0H			;
	OUT	(IDEHEAD),A		;	
	CALL	IDE_WAIT_BUSY_READY	;
	RET				;

;__DELAY____________________________________________________________________________________________________________________
; DELAY 
;___________________________________________________________________________________________________________________________
DELAY:
	NOP				;
	NOP				;
	NOP				;
	NOP				;
	NOP				;
	NOP				;
	NOP				;
	NOP				;
	NOP				;
	NOP				;
	NOP				;
	NOP				;	
	RET

;__IDE_WAIT_BUSY_READY______________________________________________________________________________________________________
; WAIT FOR BUSY TO BE READY
;___________________________________________________________________________________________________________________________
IDE_WAIT_BUSY_READY:
	PUSH	DE			;
	PUSH 	BC			;
	LD	DE,0			;
IDE_WBSY:
	LD	B,5			;
IDE_DLP:
	DJNZ	IDE_DLP			;
	INC	DE			;
	LD	A,D			;
	OR	E			;
	JR	Z,IDE_TO		;
	IN	A,(IDESTTS)		; READ ERROR REG
	AND	%10000000		; MASK OFF BUSY BIT
	JR	NZ,IDE_WBSY		; WE WANT BUSY(7) TO BE 0 
	SCF				; CARRY 1 = OK
	POP	BC			;
	POP	DE			;
	RET				;
IDE_TO:
	POP	BC			;
	POP	DE			;
	XOR	A			; CARRY 0 = TIMED OUT
	RET				;
	

;__IDE_WAIT_DRDY_READY______________________________________________________________________________________________________
; WAIT FOR DRDY
;___________________________________________________________________________________________________________________________
IDE_WAIT_DRDY_READY:
	IN	A,(IDESTTS)		; READ ERROR REG
	AND	%01000000		; MASK OFF RDY BIT
	JR	Z,IDE_WAIT_DRDY_READY	; WE WANT RDY(6) TO BE 1 
	RET

;__IDE_WAIT_DRQ_READY_______________________________________________________________________________________________________
; WAIT FOR DRQ 
;___________________________________________________________________________________________________________________________
IDE_WAIT_DRQ_READY:
	IN	A,(IDESTTS)		; READ ERROR REG
	AND	%00001000		; MASK OFF RDY BIT
	JR	Z,IDE_WAIT_DRQ_READY	; WE WANT DRQ(3) TO BE 1
	RET

;__IDE_WAIT_DRQ_ZERO________________________________________________________________________________________________________
; WAIT FOR DRQ = 0
;___________________________________________________________________________________________________________________________
IDE_WAIT_DRQ_ZERO:
	IN	A,(IDESTTS)		; READ ERROR REG
	AND	%00001000		; MASK OFF RDY BIT
	JR	NZ,IDE_WAIT_DRQ_ZERO	; WE WANT DRQ(3) TO BE 0
	RET
	

;
;__Work_Area___________________________________________________________________________________________________________________ 
;
;	Reserved Ram For Monitor working area
;_____________________________________________________________________________________________________________________________
;
SER_BAUD:	.DS	1		; specify desired UART com rate in bps
KEYBUF:  	.TEXT "                                                                                "
DISPLAYBUF:	.DB 	00,00,00,00,00,00,00,00
IDEDEVICE:	.DB	1		; IDE DRIVE SELECT FLAG (00H=PRIAMRY, 10H = SECONDARY)
IDE_SECTOR_BUFFER:	.DS	$0200




;
;__Text_Strings_________________________________________________________________________________________________________________ 
;
;	System Text Strings
;_____________________________________________________________________________________________________________________________
;
TCRLF:
	.BYTE	CR,LF,END

PROMPT:
	.BYTE	CR,LF,'>',END

TXT_READY:
	.BYTE CR,LF
	.TEXT "          NN      NN      8888      VV      VV    EEEEEEEEEE   MM          MM"
	.BYTE CR,LF
	.TEXT "         NNNN    NN    88    88    VV      VV    EE           MMMM      MMMM"
	.BYTE CR,LF
	.TEXT "        NN  NN  NN    88    88    VV      VV    EE           MM  MM  MM  MM"
	.BYTE CR,LF
	.TEXT "       NN    NNNN    88    88    VV      VV    EE           MM    MM    MM"
	.BYTE CR,LF
	.TEXT "      NN      NN      8888      VV      VV    EEEEEEE      MM          MM"
	.BYTE CR,LF
	.TEXT "     NN      NN    88    88     VV    VV     EE           MM          MM"
	.BYTE CR,LF
	.TEXT "    NN      NN    88    88      VV  VV      EE           MM          MM"
	.BYTE CR,LF
	.TEXT "   NN      NN    88    88        VVV       EE           MM          MM"
	.BYTE CR,LF
	.TEXT "  NN      NN      8888           V        EEEEEEEEEE   MM          MM    S B C"
	.BYTE CR,LF
	.BYTE CR,LF                                                                                                                                                
	.TEXT "  ****************************************************************************"
	.BYTE CR,LF
	.TEXT "Monitor Ready "
	.BYTE CR,LF,END

TXT_COMMAND:
	.BYTE CR,LF
	.TEXT "UNKNOWN COMMAND."
	.BYTE END

TXT_CKSUMERR:
	.BYTE CR,LF
	.TEXT "CHECKSUM ERROR."
	.BYTE END
CPUUP:
	.DB 	084H,0EEH,0BBH,080H,0BBH,0EEH,0CBH,084H
ADDR:
	.DB 	00H,00H,00H,00H,08CH,0BDH,0BDH,0FEH

BOOT:
	.DB 	00H,00H,80H,80H,094H,09DH,09DH,09FH

PORT:
	.DB 	00H,00H,80H,80H,094H,08CH,09DH,0EEH
SEC:
	.DB 	80H,80H,80H,80H,80H,0CBH,0CFH,0D7H

;_ATAPI COMMAND PACKETS______________________________________________________________________________________________________
; 
;
READ_DISK_PACKET
	.DB	0A8H,00H,00H,00H,00H,01H,00H,00H,00H,01H,00H,00H
ATAPI_REQUEST_SENSE
	.DB	03H,00H,00H,00H,011H,00H,00H,00H,00H,00H,00H,00H


;_KB Decode Table__________________________________________________________________________________________________________
; 
;
KB_Decode:
;                0  1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
	.DB	41H,02H,42H,82H,04H,44H,84H,08H,48H,88H,10H,50H,90H,20H,60H,0A0H
;               FW  BK  CL  EN  DP  EX  GO  BO
	.DB	01H,81H,0c1H,0c2H,0c4H,0c8H,0D0H,0E0H
;
; F-Keys,
; FW = Forward
; BK = Backward
; CL = Clear
; EN = Enter
; DP = Deposit (into mem)
; EX = Examine (Mem)
; GO = GO
; BO = Boot
;_________________________________________________________________________________________________________________________
;_HEX 7_SEG_DECODE_TABLE__________________________________________________________________________________________________
; 
; 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, ,-
; AND with 7FH to turn on DP.
;_________________________________________________________________________________________________________________________
SEGDECODE:
	.DB	0FBH,0B0H,0EDH,0F5H,0B6H,0D7H,0DFH,0F0H,0FFH,0F7H,0FEH,09FH,0CBH,0BDH,0CFH,0CEH,080H,084H,00H,0EEH,09DH

;********************* END OF PROGRAM ***********************************
.ORG	$90FF
.BYTE	$00
.END
